// via: https://jkchao.github.io/typescript-book-chinese/typings/enums.html
// 有静态方法的枚举
// 你可以使用 enum + namespace 的声明的方式向枚举类型添加静态方法。如下例所示，我们将静态成员 isBusinessDay 添加到枚举上：

// # 枚举其实在值空间 定义的值 和 标识符的 同名绑定，且总是能获取到 等同于标识符的值
// only 工作日
enum Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
}
/// enum 的合并
enum Weekday {
  Saturday = 5,
  Sunday,
}
namespace Weekday {
  export function isBusinessDay(day: Weekday) {
    switch (day) {
      case Weekday.Saturday:
      case Weekday.Sunday:
        return false;

      case Weekday.Monday:
      case Weekday.Tuesday:
      case Weekday.Wednesday:
      case Weekday.Thursday:
      case Weekday.Friday:
        return true;
      default:
        day;
        //       ^?
        throw new Error('Invalid day');
    }
  }
  export function isWeekend(day: Weekday) {
    return !Weekday.isBusinessDay(day);
  }
  export function nextDay(day: Weekday) {
    return Weekday[(day + 1) % 7];
  }
  export function prevDay(day: Weekday): string {
    return Weekday[(day + 6) % 7];
  }
  export function getDayName(day: Weekday): string {
    return Weekday[day];
  }
}

const mon = Weekday.Monday;
const sun = Weekday.Sunday;

console.log(Weekday.isBusinessDay(mon)); // true
console.log(Weekday.isBusinessDay(sun)); // false
console.log(Weekday.isWeekend(mon)); // false
console.log(Weekday.nextDay(sun)); // 0
console.log(Weekday.prevDay(sun)); // 6
console.log(Weekday.getDayName(sun)); // Sunday
console.log(Weekday.getDayName(mon)); // Monday

// # 2 枚举也是合并的，且对值有影响
enum Color {
  Red,
  Green,
  Blue,
}
// 第二次定义的 enum 会进行一次 值检查，如发现 enum 的总定义有重复的值，就会报错
enum Color {
  DarkRed = 3,
  DarkGreen,
  DarkBlue,
}
const w = Color[3];
interface CallMeWithNewToGetString {
  (): string;
}
type everyKeyof = keyof undefined;
//       ^?
class Person {
  firstName: string = 'John';
  lastName: string = 'Doe';
  // 如果只有 get 访问器，那么这个属性是只读的
  get fullName() {
    return this.firstName + this.lastName;
  }
  // 如果只有 set 访问器，那么这个属性是只写的？不，读的时候不报错，可以读到 undefined
  set fullName2(newName: string) {
    [this.firstName, this.lastName] = newName.split(' ');
  }
}

const person = new Person();
console.log(person.fullName2); // John Doe
// person.fullName = 'Dear Reader'; // Error, fullName 只读
